package com.fuyun.rpc.admin.service;

import cn.hutool.json.JSONUtil;
import com.fuyun.rpc.admin.entity.ServiceInfo;
import com.fuyun.rpc.admin.entity.StatisticsInfo;
import com.fuyun.rpc.common.domain.ServiceMetaInfo;
import io.etcd.jetcd.Client;
import io.etcd.jetcd.KV;
import io.etcd.jetcd.KeyValue;
import io.etcd.jetcd.options.GetOption;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import javax.annotation.PostConstruct;
import java.nio.charset.StandardCharsets;
import java.time.Duration;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 注册中心服务类
 */
@Service
public class RegistryService {

	@Value("${fuyun.rpc.registry.address}")
	private String registryAddress;

	@Value("${fuyun.rpc.registry.username}")
	private String username;

	@Value("${fuyun.rpc.registry.password}")
	private String password;

	private Client client;
	private KV kvClient;

	private static final String ETCD_ROOT_PATH = "/fuyun-rpc/";

	@PostConstruct
	public void init() {
		this.client = Client.builder()
			.endpoints(registryAddress)
			.user(io.etcd.jetcd.ByteSequence.from(username, StandardCharsets.UTF_8))
			.password(io.etcd.jetcd.ByteSequence.from(password, StandardCharsets.UTF_8))
			.connectTimeout(Duration.ofMillis(5000))
			.build();
		this.kvClient = client.getKVClient();
	}

	/**
	 * 获取所有服务信息
	 *
	 * @return 服务信息列表
	 */
	public List<ServiceInfo> getAllServices() {
		try {
			String searchPrefix = ETCD_ROOT_PATH;
			GetOption getOption = GetOption.builder()
				.isPrefix(true)
				.build();
			List<KeyValue> keyValues = kvClient.get(
					io.etcd.jetcd.ByteSequence.from(searchPrefix, StandardCharsets.UTF_8), getOption)
				.get()
				.getKvs();

			return keyValues.stream()
				.map(keyValue -> {
					String value = keyValue.getValue()
						.toString(StandardCharsets.UTF_8);
					ServiceMetaInfo metaInfo = JSONUtil.toBean(value, ServiceMetaInfo.class);
					return convertToServiceInfo(metaInfo);
				})
				.collect(Collectors.toList());
		} catch (Exception e) {
			throw new RuntimeException("获取服务列表失败", e);
		}
	}

	/**
	 * 根据服务名称获取服务信息
	 *
	 * @param serviceName 服务名称
	 * @return 服务信息列表
	 */
	public List<ServiceInfo> getServicesByName(String serviceName) {
		try {
			String searchPrefix = ETCD_ROOT_PATH + serviceName;
			GetOption getOption = GetOption.builder()
				.isPrefix(true)
				.build();
			List<KeyValue> keyValues = kvClient.get(
					io.etcd.jetcd.ByteSequence.from(searchPrefix, StandardCharsets.UTF_8), getOption)
				.get()
				.getKvs();

			return keyValues.stream()
				.map(keyValue -> {
					String value = keyValue.getValue()
						.toString(StandardCharsets.UTF_8);
					ServiceMetaInfo metaInfo = JSONUtil.toBean(value, ServiceMetaInfo.class);
					return convertToServiceInfo(metaInfo);
				})
				.collect(Collectors.toList());
		} catch (Exception e) {
			throw new RuntimeException("获取服务列表失败", e);
		}
	}

	/**
	 * 获取统计信息
	 *
	 * @return 统计信息
	 */
	public StatisticsInfo getStatistics() {
		List<ServiceInfo> services = getAllServices();
		StatisticsInfo stats = new StatisticsInfo();

		stats.setTotalServices(services.size());

		long onlineCount = services.stream()
			.filter(service -> "online".equals(service.getStatus()))
			.count();
		stats.setOnlineServices((int)onlineCount);
		stats.setOfflineServices(services.size() - (int)onlineCount);

		// 这里应该从监控系统获取真实的调用统计数据
		// 暂时使用模拟数据
		stats.setTotalCalls(10000);
		stats.setSuccessCalls(9800);
		stats.setFailedCalls(200);
		stats.setAverageResponseTime(45.5);
		stats.setMaxResponseTime(200);
		stats.setMinResponseTime(10);

		return stats;
	}

	/**
	 * 转换服务元信息为服务信息
	 *
	 * @param metaInfo 服务元信息
	 * @return 服务信息
	 */
	private ServiceInfo convertToServiceInfo(ServiceMetaInfo metaInfo) {
		ServiceInfo serviceInfo = new ServiceInfo();
		serviceInfo.setServiceName(metaInfo.getServiceName());
		serviceInfo.setServiceVersion(metaInfo.getServiceVersion());
		serviceInfo.setServiceGroup(metaInfo.getServiceGroup());
		serviceInfo.setServiceAddress(metaInfo.getServiceHost());
		serviceInfo.setServicePort(metaInfo.getServicePort());
		serviceInfo.setStatus("online"); // 简化处理，实际应该检查心跳
		return serviceInfo;
	}

	/**
	 * 关闭客户端连接
	 */
	public void close() {
		if (kvClient != null) {
			kvClient.close();
		}
		if (client != null) {
			client.close();
		}
	}
}